Shielded Transaction in Zcash
簡略化し、UXTOをある1つのアドレスが有している1BTC量と想定する。
つまり、ノードのデータベースは以下のようにownerのpubKeyのリストから成っていると想定。
$ Note_1 = PK_1, Note_2 = PK_2, Note_3 = PK_3
ここで、それぞれのNoteはランダム値(unique identifier)$ rを含んでいるとすると以下のようになる。
$ Note_1 = (PK_1, r_1), Note_2 = (PK_2, r_2), Note_3 = (PK_3, r_3)
以上が準備。
Noteの秘匿化のためシンプルにそれぞれのNoteをハッシュ化する。
$ H_1 = hash(Note_1), H_2 = hash(Note_2), H_3 = hash(Note_3)
ノードはspentしたされたnoteのハッシュ値も保持し続ける。
(実際には、ハッシュ値はリストではなくMerkle treeで保持され、さらにただのハッシュではなく、noteのcomputationally hidingとbinding commitmentを保持する必要がある。)
nullifier
spentしたNotesの識別子$ rのハッシュ値のリスト。
それぞれのノードはハッシュ化されたNotesに加えて、このnullifier setを保持している。
例えば、$ Note_2がspentされたらノードは$ nf_1 = hash(r_2)というnullifier setを持つことになる。(実際には、nullifierはspending keyを加えた形式で定義。)
送金
アリスが持っている$ Note_1を$ PK_4であるボブに秘匿送金することを考える。ここではアリスとボブが仮に両者間でプライベートなチャネルを有していると仮定する。
アリスはランダムに$ r_4を識別子として選び、$ Note_4 = (PK_4, r_4)を新しく定義する。
アリスはボブにoffchainプライベートチャネルで$ Note_4を送る。
アリスはonchainで$ Note_1のnullifierである$ nf_2 = hash(r_1)を送る。
アリスはonchainで新しいnoteのハッシュ値である$ H_4 = hash(Note_4)を送る。
これにより、$ nf_2がnullifier setに加えられたことで$ Note_1はspentになり、ボブが保持する$ Note_4が新しくNotesリストに加えられたことになる。$ Note_4に対応する$ r_4のnullifierはセットされていないのでunspent。
しかしこの場合、$ Note_1がnullfiierによる確かにunspentであることを検証できているが、$ Note_1がアリスが保持しているかは検証できていない。(アリスはプライベートな方法でボブに$ Note_1を送っているので。)
アリスが$ hash(Note_1)ではなく$ Note_1をブロードキャストすればすでにブロードキャストされている$ H_1とハッシュ値が一致するかで検証できるがプライバシーの問題からこれを行うことはできない。
そのため、アリスは$ PK_1, sk_1, r_1を知っていることに対するゼロ知識証明πをパブリッシュする。つまり、以下を検証。
.$ Note_1 = (PK_1, r_1)のハッシュがハッシュnoteのリストに存在している
.$ sk_1が$ PK_1に対応した秘密鍵である。(これにより確かにアリスが$ Note_1のownerであることを証明)
.$ r_1のハッシュ値が$ nf_2。($ nf_2がnullifierセットに存在しなければ$ Note_1はunspentである)
details
shieldedな支払いによって新しく作られたnoteに対して以下のcommitment(UTXO相当)がパブリッシュされる。(rho:noteの識別子、rはランダムナンス)
$ Commitment = hash(recipient Address, amount, rho, r)
$ Nullifier = hash(spending Key, rho)
それぞれのshelded transferにおいてinputの合計がoutputに一致しているか
senderがinput notesのprivate spending keysを持っていることを証明しているか
トランザクションの署名がprivate spending keyによって行われているか
それぞれのinput noteに対するcommitmentが存在するか
nullifierとnote commitmentは正しく計算されているか
nullifierが他のnoteのnullifierと衝突しないか
User Expectations at Sprout Pt. 2: Software Usability and Hardware Requirements
Anatomy of A Zcash Transaction
more details
暗号化されたNoteに対して復号化できる秘密鍵を持っている(=Noteの所有者)だけがそのValue、コミットメントなどのパラメタを得ることができるので、復号化自体のプロセスはzkに含める必要はない。
witness (cm tree) のpositionがnullifier計算のパラメタの1つになる。
sending notes (sprout)
joinSplit key pairの生成
randomSeedの生成
input noteを選択
output noteの生成
ランダムコミットメントの生成
($ \rhoの計算)
Noteコミットメントの計算 (a_pk, value, rho)
np = (value, rho, rcm, memo)の生成
受け手のtransmission keys (public key)で暗号化
全てのJoinSplit descriptionsを生成したら、non-malleabilityのためdataToBeSignedを実行
Trancking Note in wallet
sapling specs